package kku.cs.fgl;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberInputStream;
import java.io.LineNumberReader;
import java.util.Properties;
import java.util.TreeMap;
import java.util.Vector;

import kku.cs.util.ColorUtils;
import kku.cs.util.StringUtil;

import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.util.ResourceLoader;

public class SpriteManager {

	private TreeMap<String, SpriteGroup> groupMap = new TreeMap<String, SpriteGroup>();
	private TreeMap<String, SpriteSheet> sheetMap = new TreeMap<String, SpriteSheet>();
	private TreeMap<String, Image> imagesMap = new TreeMap<String, Image>();

	public SpriteManager() {

	}

	public void add(String name, SpriteSheet sheet) {
		sheetMap.put(name, sheet);
	}

	public void add(String groupname, SpriteCell... cells) {
		SpriteGroup gr = groupMap.get(groupname);
		if (gr == null) {
			gr = new SpriteGroup();
			groupMap.put(groupname, gr);
		}
		gr.add(cells);
	}

	public void add(String groupname, SpriteSheet sheet, int... cellsNo) {
		SpriteCell[] cells = new SpriteCell[cellsNo.length];
		for (int i = 0; i < cellsNo.length; i++) {
			cells[i] = sheet.getCell(cellsNo[i]);
		}
		add(groupname, cells);
	}

	public void add(String groupname, SpriteSheet sheet, String cellsList) {
		String[] cellsA = cellsList.split(",");
		Vector v = new Vector();
		for (int i = 0; i < cellsA.length; i++) {
			try {
				int cno = Integer.parseInt(cellsA[i]);
				v.add(new Integer(cno));
			} catch (Exception e) {
			}
		}
		int cellsNo[] = new int[v.size()];
		for (int i = 0; i < v.size(); i++) {
			cellsNo[i] = ((Integer) (v.get(i))).intValue();
		}
		add(groupname, sheet, cellsNo);
	}

	public SpriteGroup getGroup(String groupname) {
		return getGroup(groupname, false);
	}

	public SpriteGroup getGroup(String groupname, boolean autoCreate) {
		SpriteGroup g = groupMap.get(groupname);
		if (autoCreate && g == null) {
			g = new SpriteGroup();
			groupMap.put(groupname, g);
		}
		return g;
	}

	public SpriteSheet getSheet(String name) {
		return (SpriteSheet) (sheetMap.get(name));
	}
	
	public void clear(){
		groupMap.clear();
		sheetMap.clear();
		imagesMap.clear();		
	}

	/**
	 * Read Sprite Define from file File Format (ini) image.name=filename
	 * sheet.name=image.name
	 * 
	 * @param file
	 */
	public void load(String file) {
		// format
		int mode = 0;
		
		String sheetName = "";
		String spriteName = "";
		BufferedInputStream in = ResourceLoader.getResourceAsStream(file);
		if (in != null) {
			// prop.
			// LineNumberInputStream lin = new LineNumberInputStream(in);
			LineNumberReader lin = new LineNumberReader(new InputStreamReader(
					in));
			try {
				String s;
				while ((s = lin.readLine()) != null) {
					s = s.trim();
					if (s.length() < 2)
						continue;
					if (s.charAt(0) == '#')
						continue;
					if (s.startsWith("[images")) {
						mode = 1;
						continue;
					}
					if (s.startsWith("[sheet")) {
						String v[] = s.split("=");
						sheetName = v[1].substring(0, v[1].indexOf(']')).trim();
						mode = 2;
						continue;
					}
					if (s.startsWith("[sprite")) {
						String v[] = s.split("=");
						spriteName = v[1].substring(0, v[1].indexOf(']'))
								.trim();
						mode = 3;
						continue;
					}

					try {
						if (mode == 1)
							load_images(s);
						if (mode == 2)
							load_sheet(sheetName, s);
						if (mode == 3)
							load_sprite(spriteName, s);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private void load_sprite(String spriteName, String s) {
		SpriteGroup g = getGroup(spriteName, true);
		if (s.startsWith("delay")) {
			String v[] = StringUtil.split(s, "=");
			g.setDelay(Integer.parseInt(v[1]));
			System.out.println(spriteName+".setDelay("+v[1]+")");			
			return;
		}
		String data[] = s.split(":");
		SpriteSheet sheet = null;
		int cellno = 0, x = 0, y = 0, delay = -1;
		boolean fh = false, fv = false;

		// parse cell list
		for (String a : data[0].split(",")) {
			// sheet.index
			// System.out.println("   ("+a+")");
			String scell[] = StringUtil.split(a, '.');
			sheet = getSheet(scell[0]);
			cellno = Integer.parseInt(scell[1]);
		}
		// parse option
		if (data.length >= 2) {
			for (String a : data[1].split(",")) {
				String v[] = StringUtil.split(a, "=");
				if (v[0].equalsIgnoreCase("h"))
					fh = true;
				else if (v[0].equalsIgnoreCase("v"))
					fh = true;
				else if (v[0].equalsIgnoreCase("x")) {
					x = Integer.parseInt(v[1]);
				} else if (v[0].equalsIgnoreCase("y")) {
					y = Integer.parseInt(v[1]);
				} else if (v[0].equalsIgnoreCase("delay")) {
					delay = Integer.parseInt(v[1]);
				}
			}
		}
		if (sheet != null) {
			SpriteCell cell = sheet.getCell(cellno);
			if (cell != null) {
				g.add(cell, x, y, fh, fv, delay);
			}
		}
	}

	private void load_sheet(String sheetName, String s) {
		String v[] = StringUtil.split(s, '(', ',', ')');
		SpriteSheet st = getSheet(sheetName);
		if (st == null) {
			st = new SpriteSheet();
			sheetMap.put(sheetName, st);
		}
		int p1 = s.indexOf('(');
		int p2 = s.indexOf(')');
		if (p1 == 0 || p2 == 0)
			return;
		int n[] = new int[5];
		for (int i = 2; i < v.length; i++) {
			if(v[i].length()==0)continue;
			n[i - 2] = Integer.parseInt(v[i]);
		}
		if (v[0].equalsIgnoreCase("addcells")) {
			Image g = getImage(v[1]);
			st.addSheet(g, n[0], n[1], n[2]);
		} else if (v[0].equalsIgnoreCase("addcell")) {
			Image g = getImage(v[1]);
			if (v.length >= 4) {
				st.add(g, n[0], n[1], n[2], n[3]);
			} else {
				st.add(g);
			}
		}
	}

	private void load_images(String s) {
//		System.out.println("load_images("+s+")");
		String v[] = StringUtil.split(s,'=',',');
		if (v.length >= 2) {
			try {
				Color c=null;
				if(v.length>2){
					c=new Color(v[2]);
				}
//				System.out.println(" img="+v[0]+" src="+v[1]);
				Image img = new Image(v[1],c);
				imagesMap.put(v[0], img);
			} catch (SlickException e) {
				e.printStackTrace();
			}

		}
	}

	public Image getImage(String img) {
		if (imagesMap.containsKey(img)) {
			return imagesMap.get(img);
		}
		return null;
	}

}
